﻿<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="../helpproject.xsl" ?>
<topic template="Default" lasteditedby="Geert" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../helpproject.xsd">
  <title translate="true">Weak events</title>
  <keywords>
    <keyword translate="true">Events</keyword>
    <keyword translate="true">Weak events</keyword>
  </keywords>
  <body>
    <header>
      <para styleclass="Heading1"><text styleclass="Heading1" translate="true">Weak events</text></para>
    </header>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">You have probably heard about weak events before. This documentation is not about the issue of the cause of weak events, there are lots of articles about that. This documentation writes about the solution, which is the </text><link displaytype="text" defaultstyle="true" type="topiclink" href="T_Catel_WeakEventListener`3" styleclass="Normal" translate="true">WeakEventListener</link><text styleclass="Normal" translate="true">. Shortly said, when you do this in every class (just for the sake of explaining the problem, don’t start thinking this code has no business value):</text></para>
    <para styleclass="Code Example"><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">var log = Log.Instance;</text><br/><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">log.LogReceived += OnLogReceived;</text></para>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">As you can see, the log is a singleton, so there is only one living instance of the </text><text styleclass="Normal" style="font-style:italic;" translate="true">Log</text><text styleclass="Normal" translate="true"> class. It will probably live as long as the app itself. Now you might be thinking: what’s wrong with this code? Nothing, until the app starts growing and growing and your users start complaining about memory issues.</text></para>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">What happens here is that you subscribe to the </text><text styleclass="Normal" style="font-style:italic;" translate="true">LogReceived</text><text styleclass="Normal" translate="true"> event of the Log class. This subscription contains 2 things:</text></para>
    <list id="197" type="ol" listtype="decimal" formatstring="%0:s." format-charset="DEFAULT_CHARSET" levelreset="true" legalstyle="false" startfrom="1" styleclass="Normal (list)" style="font-family:Arial; font-size:10pt; color:#000000;">
      <li styleclass="Normal (list)"><text styleclass="Normal (list)" translate="true">What class do I need to call (null for static, otherwise the instance of the class)</text></li>
      <li styleclass="Normal (list)"><text styleclass="Normal (list)" translate="true">What method do I need to call</text></li>
    </list>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">So, in fact now the </text><text styleclass="Normal" style="font-style:italic;" translate="true">Log</text><text styleclass="Normal" translate="true"> class knows about the instance of the class that just subscribed to it and holds a reference to it (how else can it deliver the event, if it doesn’t know the address). Thus, the classes that subscribe to the </text><text styleclass="Normal" style="font-style:italic;" translate="true">Log </text><text styleclass="Normal" style="font-style:normal;" translate="true">and that do no unsubscribe will never be collected by the garbage collection.</text></para>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">I truly hope you understand the issue. If not, I recommend to read </text><link displaytype="text" defaultstyle="true" type="weblink" href="http://blog.thekieners.com/2010/02/11/simple-weak-event-listener-for-silverlight/" target="_blank" styleclass="Normal" translate="true">this excellent article</link><text styleclass="Normal" translate="true">, it dives into the issue a bit better.</text></para>
    <para styleclass="Heading1"><text styleclass="Heading1" translate="true">Open instance delegates</text></para>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">The key feature behind this implementation of the weak event pattern is open instance delegates. You are probably wondering: what the hell are open instance delegates? Well, good question, and I will try to explain it. An open instance delegate is just as a regular delegate, it points to the method of a specific class, but the biggest difference is that it does not bind to a specific instance. This means that it can be described as: I know you live on that street (method), but I have not clue in which city (instance) that is. The instance can be specified later. The delegate for a regular event handler looks like this:</text></para>
    <para styleclass="Code Example"><text styleclass="Code Example" style="font-weight:bold; font-style:normal; text-decoration:none; color:#000080;" translate="true">public</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true"> </text><text styleclass="Code Example" style="font-weight:bold; font-style:normal; text-decoration:none; color:#000080;" translate="true">delegate</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true"> </text><text styleclass="Code Example" style="font-weight:bold; font-style:normal; text-decoration:none; color:#000080;" translate="true">void</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true"> OpenInstanceHandler(TTarget @</text><text styleclass="Code Example" style="font-weight:bold; font-style:normal; text-decoration:none; color:#000080;" translate="true">this</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true">, </text><text styleclass="Code Example" style="font-weight:bold; font-style:normal; text-decoration:none; color:#000080;" translate="true">object</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true"> sender, TEventArgs e);</text></para>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">The @this is nothing special, it allows us to use the </text><text styleclass="Normal" style="font-style:italic;" translate="true">this</text><text styleclass="Normal" translate="true"> keyword so everyone knows that the target should be passed there. As you can see, it contains 3 parameters. The first one is the target (the city), the second and third parameters are the parameters of the regular event handler.</text></para>
    <para styleclass="Heading1"><text styleclass="Heading1" translate="true">Weak references</text></para>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">he weak event listener creates an open instance delegate and stores both the source and target in a </text><text styleclass="Normal" style="font-style:italic;" translate="true">WeakReference</text><text styleclass="Normal" translate="true"> class. As soon as one of these references are no longer valid, the class is unbound. The good side of this approach is that this weak event listener does not leak when the event never fires.</text></para>
    <para styleclass="Heading1"><text styleclass="Heading1" translate="true">What does it support</text></para>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">The following use cases are supported:</text></para>
    <list id="198" type="ul" listtype="bullet" formatstring="·" format-charset="SYMBOL_CHARSET" levelreset="true" legalstyle="false" startfrom="1" styleclass="Normal (list)" style="font-family:Symbol; font-size:10pt; color:#000000;">
      <li styleclass="Normal (list)"><text styleclass="Normal (list)" translate="true">Instance source (event) and instance target (handler)</text></li>
      <li styleclass="Normal (list)"><text styleclass="Normal (list)" translate="true">Static source (event) and instance target (handler)</text></li>
      <li styleclass="Normal (list)"><text styleclass="Normal (list)" translate="true">Instance source (event) and static target (handler)</text></li>
    </list>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">So, actually it handles everything that can cause a memory leak via event subscriptions!</text></para>
    <para styleclass="Heading1"><text styleclass="Heading1" translate="true">What does it not support and what are the downsides</text></para>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">This weak event listener follows the rules of the .NET framework. So, it cannot subscribe to private events. If you want private events, do your own hacking (the source is available, you only have to change the </text><text styleclass="Normal" style="font-style:italic;" translate="true">DefaultEventBindingFlags </text><text styleclass="Normal" translate="true">at the top of the class).</text></para>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">There are a few downsides about using a weak event listeners in general:</text></para>
    <list id="199" type="ul" listtype="bullet" formatstring="·" format-charset="SYMBOL_CHARSET" levelreset="true" legalstyle="false" startfrom="1" styleclass="Normal (list)" style="font-family:Symbol; font-size:10pt; color:#000000;">
      <li styleclass="Normal (list)"><text styleclass="Normal (list)" translate="true">It’s notation is ugly, the “original” .NET way looks way better</text></li>
      <li styleclass="Normal (list)"><text styleclass="Normal (list)" translate="true">You have to name the event by string, that sucks (if you know a better way, contact me!)</text></li>
      <li styleclass="Normal (list)"><text styleclass="Normal (list)" translate="true">It can only handle events with a handler of EventHandler&lt;TEventArgs&gt;</text></li>
      <li styleclass="Normal (list)"><text styleclass="Normal (list)" translate="true">You become a lazy developer not caring about subscriptions</text></li>
    </list>
    <para styleclass="Heading1"><text styleclass="Heading1" translate="true">How to use</text></para>
    <para styleclass="Normal"><text styleclass="Normal" style="font-weight:normal;" translate="true">There are 4 categories of event subscriptions, all described below.</text></para>
    <para styleclass="Normal"><text styleclass="Normal" style="font-weight:bold;" translate="true">Instance to instance</text><br/><text styleclass="Normal" style="font-weight:normal;" translate="true">This is the situation where an instance target subscribes to an instance event. The events are unbound as soon as either the target or source are collected.</text></para>
    <para styleclass="Code Example"><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true">var source = </text><text styleclass="Code Example" style="font-weight:bold; font-style:normal; text-decoration:none; color:#000080;" translate="true">new</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true"> EventSource();</text><br/><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true">var listener = </text><text styleclass="Code Example" style="font-weight:bold; font-style:normal; text-decoration:none; color:#000080;" translate="true">new</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true"> EventListener();</text><br/><br/><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true">var weakEventListener = WeakEventListener&lt;EventListener, EventSource, EventArgs&gt;.SubscribeToWeakEvent(listener, source, &quot;PublicEvent&quot;, listener.OnPublicEvent);</text></para>
    <para styleclass="Normal"><text styleclass="Normal" style="font-weight:bold;" translate="true">Instance to static</text><br/><text styleclass="Normal" style="font-weight:normal;" translate="true">This is the situation where a static target subscribes to an instance event. The events are unbound as soon as the source is collected.</text></para>
    <para styleclass="Code Example"><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true">var source = </text><text styleclass="Code Example" style="font-weight:bold; font-style:normal; text-decoration:none; color:#000080;" translate="true">new</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true"> EventSource();</text><br/><br/><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true">var weakEventListener = WeakEventListener&lt;EventListener, EventSource, EventArgs&gt;.SubscribeToWeakEvent(</text><text styleclass="Code Example" style="font-weight:bold; font-style:normal; text-decoration:none; color:#000080;" translate="true">null</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true">, source, &quot;PublicEvent&quot;, EventListener.OnEventStaticHandler);</text></para>
    <para styleclass="Normal"><text styleclass="Normal" style="font-weight:bold;" translate="true">Static to instance</text><br/><text styleclass="Normal" style="font-weight:normal;" translate="true">This is the situation where an instance target subscribes to a static event. The events are unbound as soon as the target is collected.</text></para>
    <para styleclass="Code Example"><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true">var listener = </text><text styleclass="Code Example" style="font-weight:bold; font-style:normal; text-decoration:none; color:#000080;" translate="true">new</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true"> EventListener();</text><br/><br/><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true">var weakEventListener = WeakEventListener&lt;EventListener, EventSource, EventArgs&gt;.SubscribeToWeakEvent(listener, </text><text styleclass="Code Example" style="font-weight:bold; font-style:normal; text-decoration:none; color:#000080;" translate="true">null</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true">, &quot;StaticEvent&quot;, listener.OnPublicEvent);</text></para>
    <para styleclass="Normal"><text styleclass="Normal" style="font-weight:bold;" translate="true">Static to static</text><br/><text styleclass="Normal" style="font-weight:normal;" translate="true">This is not supported because you shouldn’t be using a weak event listener here. Static events with static event handlers simply cannot cause memory leaks because both the source and the target have no instance. However, it might be possible that you subscribe to an event too many times and the event fires too many times. But again, no memory issues here.</text></para>
  </body>
</topic>
